/*
 * Search Engine Safe Url Filter
 * Author: Scott Van Vliet, svanvliet@hitachiconsulting.com
 * Date: 2004-05-03
 */ 

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Boardworks.Utilities.SearchEngineSafe
{
	/// <summary>
	/// Summary description for SesRequestFilter.
	/// </summary>
	public class SesRequestFilter : Stream
	{
		/// <summary>
		/// 
		/// </summary>
		private Stream m_BaseStream;

		/// <summary>
		/// 
		/// </summary>
		private HttpContext m_Context;

		/// <summary>
		/// 
		/// </summary>
		private Stream BaseStream
		{
			get
			{
				return this.m_BaseStream;
			}
			set
			{
				this.m_BaseStream = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		private HttpContext Context
		{
			get
			{
				return this.m_Context;
			}
			set
			{
				this.m_Context = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="baseStream"></param>
		/// <param name="context"></param>
		public SesRequestFilter(Stream baseStream, HttpContext context)
		{
			this.BaseStream = baseStream;
			this.Context = context;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="buffer"></param>
		/// <param name="offset"></param>
		/// <param name="count"></param>
		public override void Write(byte[] buffer, int offset, int count) 
		{
			string sBuffer = Encoding.Default.GetString(buffer, offset, count);
			MatchCollection hrefMatches = Regex.Matches(sBuffer, SesRegexPattern.HrefPattern, RegexOptions.IgnoreCase);

			//
			// Debug
			//
			FileStream fs = File.OpenWrite(String.Format(@"C:\Temp\seslog-{0}.txt", DateTime.Now.Ticks));
			fs.Write(buffer, offset, count);
			fs.Flush();
			fs.Close();

			if (hrefMatches.Count > 0)
			{
				foreach (Match match in hrefMatches)
				{
					string href = match.Groups[match.Groups.Count - 2].Value;
					if (Regex.IsMatch(href, SesRegexPattern.AspxPattern) &&
						!Regex.IsMatch(match.Value, SesRegexPattern.ImgPattern) &&
						!Regex.IsMatch(match.Value, SesRegexPattern.CssPattern) &&
						!Regex.IsMatch(match.Value, SesRegexPattern.ScriptPattern))
					{
						href = href.Replace(href, SesUrlUtil.ToSesUrl(href));
					}
					if (!Regex.IsMatch(href, SesRegexPattern.HttpProtocolPattern) &&
						!Regex.IsMatch(href, SesRegexPattern.MailToPattern) &&
						!Regex.IsMatch(href, SesRegexPattern.AnchorPattern) &&
						!Regex.IsMatch(href, SesRegexPattern.JavascriptHtmlStatementPattern))
					{
						if (!Regex.IsMatch(href, SesRegexPattern.AbsolutePathPattern))
						{
							href = Regex.Match(this.Context.Request.Path, SesRegexPattern.CurrentPathPattern).Groups[1].Value + href;
						}
						sBuffer = sBuffer.Replace(match.Value, match.Value.Replace(match.Groups[match.Groups.Count - 2].Value, href));
					}
				}
			}

			byte[] bufferNew = Encoding.Default.GetBytes(sBuffer);
			this.BaseStream.Write(bufferNew, 0, bufferNew.Length);
		}

		#region Implementation Requirements

		/// <summary>
		/// 
		/// </summary>
		private long m_Position;

		/// <summary>
		/// 
		/// </summary>
		public override long Position
		{
			get
			{
				return this.m_Position;
			}
			set
			{
				this.m_Position = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public override bool CanRead
		{
			get 
			{ 
				return true;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public override bool CanSeek
		{
			get 
			{ 
				return true;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public override bool CanWrite
		{
			get 
			{ 
				return true; 
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public override long Length
		{
			get 
			{ 
				return 0;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="offset"></param>
		/// <param name="direction"></param>
		/// <returns></returns>
		public override long Seek(long offset, System.IO.SeekOrigin direction) 
		{
			return this.BaseStream.Seek(offset, direction);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="length"></param>
		public override void SetLength(long length) 
		{
			this.BaseStream.SetLength(length);
		}

		/// <summary>
		/// 
		/// </summary>
		public override void Close() 
		{
			this.BaseStream.Close();
		}

		/// <summary>
		/// 
		/// </summary>
		public override void Flush() 
		{
			this.BaseStream.Flush();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="buffer"></param>
		/// <param name="offset"></param>
		/// <param name="count"></param>
		/// <returns></returns>
		public override int Read(byte[] buffer, int offset, int count) 
		{
			return this.BaseStream.Read(buffer, offset, count);
		}
		
		#endregion

	}
}
